/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "当前默认操作数据.h"

#include <core/动画/curve.h>
#include <stack>
//#include <threads.h>
#include <thread>
#include <mutex>
#include "..\异步解算\物理异步解算.h"
#include "节点/节点.h"
#include "节点/编译声明代码.h"
#include "节点编辑.h"








static S_Scene* g_Scene = 0;
static S_物体* g_当前独立显示物体 = 0;
static S_物体* g_场景根物体 = 0;

static S_时间帧	g_场景帧 = {f_alloc_I32Prop(nullptr, L"当前帧"), f_alloc_iVec2Prop(nullptr, L"帧区间"), f_alloc_I32Prop(nullptr, L"子帧") };
static std::set<struct C_Widget*> g当前时间帧链接组件;



static std::stack<S_物体*>	g_删除物体;
static std::vector<S_物体*>	g_焦点物体;
static std::map<S_物体*, C_节点基类*> g_能在场景视口中显示的物体节点;
//std::mutex	S_模拟Ctx::物理模拟线程锁;
//uint8		S_模拟Ctx::线程模拟物理参数数量;
//static pthread_t g_Threads[128] = {};
//static pthread_mutex_t g_mutex;
//static std::thread g_Threads;
bool	S_NodeCtx_模拟计算::g_结束模拟解算 = false;
bool	S_NodeCtx_模拟计算::g_是否更新节点 = true;
S_Props	S_NodeCtx_模拟计算::g_是否开启解算 = f_alloc_BoolProp(nullptr, L"是否开启模拟计算");
S_Props	S_NodeCtx_模拟计算::g_节点解算 = f_alloc_BoolProp(nullptr, L"是否开启解算");


static S_材质* g_基本光照描边材质		= nullptr;
static S_材质* g_逐顶点线段描边材质	= nullptr;


static S_材质* g_基本光照线材质 = nullptr;
static S_材质* g_基本光照面材质 = nullptr;
static S_材质* g_权重可视线材质 = nullptr;
static S_材质* g_权重可视面材质 = nullptr;



static S_单色材质* g_单色点材质		= nullptr;
static S_单色材质* g_单色平直面材质	= nullptr;
static S_单色材质* g_单色面材质		= nullptr;
static S_单色材质* g_单色线框材质		= nullptr;
static S_单色材质* g_单色描边材质	= nullptr;
static S_单色材质* g_单色线段材质 = nullptr;
static S_单色材质* g_单色连续线材质 = nullptr;

static S_材质* g_单色连续虚线材质 = nullptr;
static S_材质* g_单色线段虚线材质	= nullptr;

static S_材质* g逐顶点线段材质 = nullptr;
static S_材质* g逐顶点线段材质_朝向镜头 = nullptr;
static S_材质* g逐顶点连续线材质 = nullptr;
static S_材质* g逐顶点_点材质	= nullptr;









S_RGBA8UI S_节点UI主题::uic_I8;
S_RGBA8UI S_节点UI主题::uic_UI8;
S_RGBA8UI S_节点UI主题::uic_I16;
S_RGBA8UI S_节点UI主题::uic_UI16;
S_RGBA8UI S_节点UI主题::uic_I32;
S_RGBA8UI S_节点UI主题::uic_UI32;
S_RGBA8UI S_节点UI主题::uic_I64;
S_RGBA8UI S_节点UI主题::uic_UI64;
S_RGBA8UI S_节点UI主题::uic_F32;
S_RGBA8UI S_节点UI主题::uic_vec2;
S_RGBA8UI S_节点UI主题::uic_vec3;
S_RGBA8UI S_节点UI主题::uic_vec4;
S_RGBA8UI S_节点UI主题::uic_mat2X2;
S_RGBA8UI S_节点UI主题::uic_mat3X2;
S_RGBA8UI S_节点UI主题::uic_mat4X2;
S_RGBA8UI S_节点UI主题::uic_mat2X3;
S_RGBA8UI S_节点UI主题::uic_mat3X3;
S_RGBA8UI S_节点UI主题::uic_mat4X3;
S_RGBA8UI S_节点UI主题::uic_mat4X4;
S_RGBA8UI S_节点UI主题::uic_对象;
S_RGBA8UI S_节点UI主题::uic_物体;
S_RGBA8UI S_节点UI主题::uic_解算器;

S_RGBA8UI S_节点UI主题::uic_模型面 = { 180, 180, 180, 255 };
S_RGBA8UI S_节点UI主题::uic_模型线 = { 20, 20, 20, 255 };
S_RGBA8UI S_节点UI主题::uic_模型焦点 = { 230, 120, 80, 255 };
//S_RGBA8UI S_节点UI主题::uic_模型焦点 = { 80, 255, 255, 255 };


S_RGBA8UI S_节点UI主题::uic_链接线 = { 100, 100, 100, 255 };
S_RGBA8UI S_节点UI主题::uic_链接线链接 = {200, 255, 150, 255};

S_RGBA8UI S_节点UI主题::uic_主线辅线 = {128,128,128,150};
S_RGBA8UI S_节点UI主题::uic_网格辅线 = {127,127,127,150};
S_RGBA8UI S_节点UI主题::uic_刻度线L1 = { 60, 60, 60, 255 };
S_RGBA8UI S_节点UI主题::uic_刻度线L2 = { 25, 25, 25, 255 };

S_RGBA8UI S_节点UI主题::uic_骨骼面物体状态 = { 200, 200, 200, 255 };
S_RGBA8UI S_节点UI主题::uic_骨骼边物体状态 = { 10, 10, 10, 255 };
S_RGBA8UI S_节点UI主题::uic_骨骼面编辑状态 = { 197, 197, 197, 255 };
S_RGBA8UI S_节点UI主题::uic_骨骼边编辑状态 = { 200, 200, 197, 255 };
S_RGBA8UI S_节点UI主题::uic_骨骼编辑焦点 = { 250, 250, 200, 255 };
S_RGBA8UI S_节点UI主题::uic_骨节编辑焦点 = { 250, 230, 150, 255 };

std::string	S_节点UI主题::ui_默认字体 = "雅黑";
std::string	S_节点UI主题::ui_节点图标 = "节点ICO";
//static void* f_物理模拟线程(void* 线程参数) {
S_Props		S_节点数据状态::g_3D视口显示模式 = {};








void f_NodeCtx_全局初始化() {
	f_prop_Bool(S_NodeCtx_模拟计算::g_是否开启解算) = false;
	S_NodeCtx_模拟计算::g_是否开启解算.m_私有 = true;
	f_prop_Bool(S_NodeCtx_模拟计算::g_节点解算) = false;
	S_NodeCtx_模拟计算::g_节点解算.m_私有 = true;


	f_prop_iVec2(g_场景帧.帧区间) = { 0, 250 };
	g_场景帧.帧区间.m_私有 = true;

	f_prop_I32(g_场景帧.当前帧) = 0;
	g_场景帧.当前帧.m_私有 = true;
	g_场景帧.当前帧.m_UI->m_LinkWidget = &g当前时间帧链接组件;

	f_prop_I32(g_场景帧.子帧) = 0;
	g_场景帧.子帧.m_私有 = true;


	S_节点数据状态::g_打开编辑模式 = f_alloc_BoolProp(nullptr, L"是否开启编辑模式");
	S_节点数据状态::g_打开编辑模式.m_私有 = true;
	f_prop_Bool(S_节点数据状态::g_打开编辑模式) = false;

	S_节点数据状态::g_网格编辑模式 = f_alloc_EnumProp(nullptr, { {L"物体模式", "物体"}, {L"编辑模式", "三角顶点"}, {L"编辑权重", "lab4"}, {L"绘制纹理", "brush"} }, L"网格编辑");
	S_节点数据状态::g_骨骼编辑模式 = f_alloc_EnumProp(nullptr, { {L"物体模式", ""}, {L"编辑模式", ""}, {L"姿态模式", ""} }, L"骨骼编辑");
	S_节点数据状态::g_灯光编辑模式 = f_alloc_EnumProp(nullptr, { {L"物体模式", ""}, {L"编辑模式", ""} }, L"灯光编辑");

	S_节点数据状态::g_网格编辑模式.m_私有 = true;
	S_节点数据状态::g_骨骼编辑模式.m_私有 = true;
	S_节点数据状态::g_灯光编辑模式.m_私有 = true;

	S_节点数据状态::g_3D视口显示模式 = f_alloc_EnumProp(nullptr,
		{ {L"点显示", "点阵"}, {L"线显示", "网格"}, {L"面显示", "球"}, {L"材质显示", "05_关照多维材质"} },
		L"显示模式",
		2);
	S_节点数据状态::g_3D视口显示模式.m_私有 = true;

	S_节点数据::g_物理引擎视口互交.m_私有 = true;
	f_prop_Bool(S_节点数据::g_物理引擎视口互交) = false;


}

void f_NodeCtx_全局释放() {
	f_NodeCtx_等待计算完成();
	f_NodeCtx_清除全局数据();


	f_prop_Release(g_场景帧.帧区间);
	f_prop_Release(g_场景帧.当前帧);
	f_prop_Release(g_场景帧.子帧);

	f_prop_Release(S_节点数据状态::g_打开编辑模式);

	f_prop_Release(S_节点数据状态::g_网格编辑模式);
	f_prop_Release(S_节点数据状态::g_骨骼编辑模式);
	f_prop_Release(S_节点数据状态::g_灯光编辑模式);
}

void f_NodeCtx_清除全局数据() {
	g_能在场景视口中显示的物体节点.clear();
	g_焦点物体.clear();

	f_OE_销毁所有可编辑物体属性();

	f_NodeCtx_get默认场景()->m_物体set.clear();
	S_节点数据::g_全局索引物体.clear();
	S_节点数据::m_全局物体set.clear();
	S_节点数据::m_独立物体set.clear();


	f_代码构建_清除代码缓存();
}

void f_NodeCtx_set默认场景(S_Scene* scene) {
	g_Scene = scene;

}

void f_NodeCtx_set场景根物体(S_设备环境& ctx) {
	g_场景根物体 = f_ob_创建物体(ctx, E_物体类型::t_空);
	g_Scene->f_add物体(g_场景根物体);
}

void f_NodeCtx_初始化物体材质(S_设备环境& ctx) {
	g_单色平直面材质	= new S_单色平直面材质(ctx);
	g_单色面材质		= new S_单色面材质(ctx);
	g_单色线框材质		= new S_单色线框材质(ctx);
	g_单色描边材质		= new S_单色描边材质(ctx);
	g_单色线段材质		= new S_单色线段材质(ctx);
	g_单色连续线材质	= new S_单色连续线材质(ctx);
	g_单色连续虚线材质	= new S_单色虚线材质(ctx, true);
	g_单色线段虚线材质	= new S_单色虚线材质(ctx, false);

	g_基本光照描边材质 = new S_基本光照描边材质(ctx);
	g_基本光照面材质 = new S_面基本光照材质(ctx);
	g_基本光照线材质 = new S_线基本光照材质(ctx);
	g_权重可视面材质 = new S_权重可视材质(ctx, E_填充模式::e_填充面);
	g_权重可视线材质 = new S_权重可视材质(ctx, E_填充模式::e_填充线);


	g_单色点材质 = new S_单色点材质(ctx);

	g逐顶点线段材质 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);
	g逐顶点线段材质_朝向镜头 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);

	g逐顶点连续线材质 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画连续线);
	g逐顶点_点材质 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画点集);
	g_逐顶点线段描边材质 = new S_单色逐顶点线描边材质(ctx);
	
	
}

//void f_NodeCtx_set帧(S_时间帧& 帧) {
//	g_场景帧 = 帧;
//}

void f_NodeCtx_set当前帧(int64 帧) {
	f_prop_I32(g_场景帧.当前帧) = 帧;
}

void f_NodeCtx_set帧区间(ivec2 区间) {
	f_prop_iVec2(g_场景帧.帧区间) = 区间;
}






S_Scene* f_NodeCtx_get默认场景() {
	return g_Scene;
}

S_物体* f_NodeCtx_get当前独立显示物体() {
	return g_当前独立显示物体;
}

S_物体* f_NodeCtx_get场景根物体() {
	return g_场景根物体;
}

S_时间帧& f_NodeCtx_get帧() {
	return g_场景帧;
}

void f_NodeCtx_set场景当前时间(int32 t) {
	f_prop_I32(g_场景帧.当前帧) = t;

	S_物体::g_更新曲线关键帧 = true;
	S_物体::g_当前帧 = t;

	f_an_更新属性关键帧();
}

void f_NodeCtx_set焦点物体(std::vector<S_物体*>& objs) {
	g_焦点物体 = objs;
}

std::vector<S_物体*>& f_NodeCtx_get焦点物体() {
	return g_焦点物体;
}

void f_NodeCtx_录物体类节点(C_节点基类* 节点) {
	if (节点->m_Type >= E_节点类型::e_节点Type_空物体) {
		auto e = 节点->f_get虚拟体();
		g_能在场景视口中显示的物体节点[e] = 节点;
	}
}

void f_NodeCtx_录物体类节点(C_节点基类* 节点, S_物体* ob) {
	if (节点->m_Type >= E_节点类型::e_节点Type_空物体) {
		g_能在场景视口中显示的物体节点[ob] = 节点;
	}
}

void f_NodeCtx_清除物体类节点(S_物体* ob) {
	g_能在场景视口中显示的物体节点.erase(ob);
}

std::vector<C_节点基类*> f_NodeCtx_从可视物体取节点(const std::vector<S_物体*>& obs) {
	std::vector<C_节点基类*> planes;
	for (auto ob : obs) {
		//auto i = g_能在场景视口中显示的物体节点.find(ob);
		if(g_能在场景视口中显示的物体节点.find(ob) != g_能在场景视口中显示的物体节点.end()) planes.push_back(g_能在场景视口中显示的物体节点[ob]);
	}
	return planes;
}







S_单色材质* f_NodeCtx_get单色点材质() {
	return g_单色点材质;
}
S_单色材质* f_NodeCtx_get单色线材质() {
	return g_单色线框材质;
}
S_单色材质* f_NodeCtx_get单色面材质() {
	return g_单色面材质;
}
S_单色材质* f_NodeCtx_get单色平直面材质() {
	return g_单色平直面材质;
}
S_单色材质* f_NodeCtx_get单色描边材质() {
	return g_单色描边材质;
}
//S_单色材质包 f_NodeCtx_get骨骼材质() {
//	return S_单色材质包();
//}


S_材质* f_NodeCtx_get单色线段材质() {
	return g_单色线段材质;
}

S_材质* f_NodeCtx_get单色连续线材质() {
	return g_单色连续线材质;
}

S_材质* f_NodeCtx_get单色连续虚线材质() {
	return g_单色连续虚线材质;
}

S_材质* f_NodeCtx_get单色线段虚线材质() {
	return g_单色线段虚线材质;
}




S_材质* f_NodeCtx_get基本光照描边材质() {
	return g_基本光照描边材质;
}

S_材质* f_NodeCtx_get基本光照线材质() {
	return g_基本光照线材质;
}

S_材质* f_NodeCtx_get基本光照面材质() {
	return g_基本光照面材质;
}

S_材质* f_NodeCtx_get权重可视线材质() {
	return g_权重可视线材质;
}
S_材质* f_NodeCtx_get权重可视面材质() {
	return g_权重可视面材质;
}




S_材质* f_NodeCtx_get逐顶点线段材质(bool 统一朝向) {
	if (统一朝向) return g逐顶点线段材质_朝向镜头;
	return g逐顶点线段材质;
}
S_材质* f_NodeCtx_get逐顶点连续线材质() {
	return g逐顶点连续线材质;
}
S_材质* f_NodeCtx_get逐顶点点材质() {
	return g逐顶点_点材质;
}
S_材质* f_NodeCtx_get线段描边材质() {
	return g_逐顶点线段描边材质;
}



S_材质* f_NodeCtx_get灯光模型中心圆材质(S_设备环境& ctx) {
	static S_材质* 灯光模型线段 = nullptr;
	if (!灯光模型线段) {
		灯光模型线段 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);
	}
	return 灯光模型线段;
}
S_材质* f_NodeCtx_get灯光模型范围线材质(S_设备环境& ctx) {
	static S_材质* 灯光模型线 = nullptr;
	if (!灯光模型线) {
		灯光模型线 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);
	}
	return 灯光模型线;
}
S_材质* f_NodeCtx_get灯光模型方向线材质(S_设备环境& ctx) {
	static S_材质* 灯光模型线 = nullptr;
	if (!灯光模型线) {
		灯光模型线 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);
	}
	return 灯光模型线;
}
S_材质* f_NodeCtx_get区域灯光模型点材质(S_设备环境& ctx) {
	return nullptr;
}

S_材质* f_NodeCtx_get单虚拟体材质(S_设备环境& ctx) {
	static S_材质* 单虚拟体线材质 = nullptr;
	if (!单虚拟体线材质) {
		单虚拟体线材质 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);
	}
	return 单虚拟体线材质;
}




S_材质* f_NodeCtx_get虚拟体中心圆材质(S_设备环境& ctx) {
	static S_材质* 虚拟体中心圆 = nullptr;
	if (!虚拟体中心圆) {
		虚拟体中心圆 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);
	}
	return 虚拟体中心圆;
}
S_材质* f_NodeCtx_get虚拟体范围线材质(S_设备环境& ctx) {
	static S_材质* 虚拟体范围线 = nullptr;
	if (!虚拟体范围线) {
		虚拟体范围线 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);
	}
	return 虚拟体范围线;
}
S_材质* f_NodeCtx_get虚拟体方向线材质(S_设备环境& ctx) {
	static S_材质* 虚拟体方向线 = nullptr;
	if (!虚拟体方向线) {
		虚拟体方向线 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);
	}
	return 虚拟体方向线;
}




S_材质* f_NodeCtx_get单元素虚拟体材质(S_设备环境& ctx) {
	static S_材质* 单元素虚拟体 = nullptr;
	if (!单元素虚拟体) {
		单元素虚拟体 = new S_线逐顶点有色线段材质(ctx, true, E_绘制方式::e_画线段);
	}
	return 单元素虚拟体;
}




void f_NodeCtx_删除物体到回收站(S_物体* ob) {
	ob->m_父物体 = nullptr;

	for (auto& sob : ob->m_子物体) {
		f_NodeCtx_删除物体到回收站(sob);
	}
	f_ob_清除子物体(ob);

	g_删除物体.push(ob);
}

S_物体* f_NodeCtx_回收物体() {
	S_物体* ob = nullptr;

	if (g_删除物体.size()) {
		ob = g_删除物体.top();
		g_删除物体.pop();
	}
	
	return ob;
}

void f_NodeCtx_物体显示模型(E_物体显示模式 模式) {
	for (auto& e : g_Scene->m_物体set) {
		switch (e->m_Type) {
		case E_物体类型::t_网格:
			switch (模式) {
			case E_物体显示模式::e_线:
				if (f_ob_get数量层数量(e) > 2) {
					e->f_打开可视通道(0);
					e->f_关闭可视通道(1);
					e->f_打开可视通道(2);
				}
				else {
					e->f_打开可视通道(0);
					e->f_关闭可视通道(1);
				}
				break;

			case E_物体显示模式::e_面:
				if (f_ob_get数量层数量(e) > 2) {
					e->f_打开可视通道(0);
					e->f_打开可视通道(1);
					e->f_关闭可视通道(2);
				}
				else {
					e->f_打开可视通道(0);
					e->f_关闭可视通道(1);
				}
				break;

			case E_物体显示模式::e_线面:
				if (f_ob_get数量层数量(e) > 2) {
					e->f_打开可视通道(0);
					e->f_打开可视通道(1);
					e->f_打开可视通道(2);
				}
				else {
					e->f_打开可视通道(0);
					e->f_打开可视通道(1);
				}
				break;

			case E_物体显示模式::e_渲染:
				//e->f_打开可视通道(1);
				//e->f_关闭可视通道(2);
				break;
			}
			break;

		case E_物体类型::t_多边形:
			switch (模式) {
			case E_物体显示模式::e_点:
				e->f_关闭可视通道(1);
				e->f_打开可视通道(2);
				e->f_关闭可视通道(3);
				break;
			case E_物体显示模式::e_线:
				e->f_关闭可视通道(1);
				e->f_关闭可视通道(2);
				e->f_打开可视通道(3);
				break;

			case E_物体显示模式::e_面:
				e->f_打开可视通道(1);
				e->f_关闭可视通道(2);
				e->f_关闭可视通道(3);
				break;

			case E_物体显示模式::e_线面:
				e->f_打开可视通道(1);
				e->f_打开可视通道(2);
				e->f_打开可视通道(3);
				break;

			case E_物体显示模式::e_渲染:
				//e->f_打开可视通道(1);
				//e->f_关闭可视通道(2);
				break;
			}
			break;
		default:
			continue;
		}
		if (f_ob_get数量层数量(e) <= 1) {
			continue;
		}

		
	}
}

void f_NodeCtx_物体显示模型(S_物体* ob, E_物体显示模式 模式) {
	if (f_ob_get数量层数量(ob) <= 1) {
		return;
	}

	switch (模式) {
	case E_物体显示模式::e_线:
		f_NodeCtx_物体线模式显示(ob);
		break;

	case E_物体显示模式::e_面:
		f_NodeCtx_物体面模式显示(ob);
		break;

	case E_物体显示模式::e_线面:
		f_NodeCtx_物体线面模式显示(ob);
		break;

	case E_物体显示模式::e_渲染:
		ob->f_打开可视通道(1);
		ob->f_关闭可视通道(2);
		break;
	}
}

void f_NodeCtx_物体线模式显示(S_物体* ob) {
	if (f_ob_get数量层数量(ob) > 2) {
		ob->f_打开可视通道(0);
		ob->f_关闭可视通道(1);
		ob->f_打开可视通道(2);
	}
	else {
		ob->f_打开可视通道(0);
		ob->f_关闭可视通道(1);
	}
}

void f_NodeCtx_物体面模式显示(S_物体* ob) {
	if (f_ob_get数量层数量(ob) > 2) {
		ob->f_打开可视通道(0);
		ob->f_打开可视通道(1);
		ob->f_关闭可视通道(2);
	}
	else {
		ob->f_打开可视通道(0);
		ob->f_关闭可视通道(1);
	}
}

void f_NodeCtx_物体线面模式显示(S_物体* ob) {
	if (f_ob_get数量层数量(ob) > 2) {
		ob->f_打开可视通道(0);
		ob->f_打开可视通道(1);
		ob->f_打开可视通道(2);
	}
	else {
		ob->f_打开可视通道(0);
		ob->f_打开可视通道(1);
	}
}






S_节点UI主题::S_节点UI主题() {

}




